
#if defined(CONFIG_TAR4ESP32)
#include "esp_netif.h"
#include "sdkconfig.h"
#endif

#include <utils.hpp>
#include <wifi_text_log.hpp>

#define SOCKET_QUEUE_SIZE (100)

static WifiTextLog* s_WifiTextLog = nullptr;

WifiTextLog* WifiTextLog::Instance(void)
{
	if (s_WifiTextLog == nullptr)
	{
		s_WifiTextLog = new WifiTextLog();
	}
	return s_WifiTextLog;
}

WifiTextLog::WifiTextLog()
	: TaskRun(PRIORITY_WIFI_TEXTLOG, 2500, "wifi_text_log")
	, m_Ip(SERVER_IP)
	, m_Port(TCP_PORT_TEXTLOG)
	, m_SemRW(1)
	, m_SemSig(0)
{
}

WifiTextLog::~WifiTextLog()
{
}

void WifiTextLog::Run(void* arg)
{
	int addr_family = 0;
	int ip_protocol = 0;

	while (1)
	{
		if (addr_family != 0)
		{
			TaskRun::mSleep(5000);
		}

		struct sockaddr_in dest_addr;
		inet_pton(AF_INET, m_Ip.c_str(), &dest_addr.sin_addr);
		dest_addr.sin_family = AF_INET;
		dest_addr.sin_port	 = htons(m_Port);
		addr_family			 = AF_INET;
		ip_protocol			 = IPPROTO_IP;

		int sock = socket(addr_family, SOCK_STREAM, ip_protocol);
		if (sock < 0)
		{
			printf("Unable to create socket: errno %d\n", errno);
			shutdown(sock, 0);
			close(sock);
			continue;
		}
		// printf("Socket created, connecting to %s:%d\n", m_Ip.c_str(), m_Port);

		int err = connect(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
		if (err != 0)
		{
			// printf("Socket unable to connect: errno %d\n", errno);
			shutdown(sock, 0);
			close(sock);
			continue;
		}
		printf("Successfully connected\n");

		while (1)
		{
			int err = 0;
			m_SemSig.Wait();
			m_SemRW.Wait();
			while (m_DataList.size() > 0)
			{
				std::string line = m_DataList.front();
				m_DataList.pop_front();
				if (SocketCheckAlive(sock))
				{
					err = send(sock, line.c_str(), line.size(), 0);
				}
			}
			m_SemRW.Post();
			if (err < 0 || !SocketCheckAlive(sock))
			{
				printf("Error occurred during sending: errno %d\n", errno);
				shutdown(sock, 0);
				close(sock);
				break;
			}
		}
		printf("Shutting down socket and restarting...\n");
		shutdown(sock, 0);
		close(sock);
	}
}

void WifiTextLog::SendTextLine(std::string line)
{
#if TCP_TEXTLOG_ENABLE
	if (line.size() <= 0)
	{
		return;
	}

	m_SemRW.Wait();
	m_DataList.push_back(line);
	while (m_DataList.size() > SOCKET_QUEUE_SIZE)
	{
		m_DataList.pop_front();
	}
	m_SemRW.Post();
	m_SemSig.Post();
#endif
}

void WifiTextLog::Start(void* arg)
{
#if TCP_TEXTLOG_ENABLE
	TaskRun::Start(arg);
#endif
}